package fi.solita.dojo.mazeserver.map

import scala.collection._
import fi.solita.dojo.mazeserver.util._
import fi.solita.dojo.mazeserver.game.internal._
import fi.solita.dojo.mazeserver.game._

object MapGenerator {
	def createSimpleMap(height: Int, width: Int) = {

		val map = createGameLocations(height, width).toList

		GameMap(immutable.Map() ++ map)
	}    

	private def createGameLocations(height: Int, width: Int) = {
		for (x <- 0 until height; y <- 0 until width) yield
		(Coordinates(x,y), randomGameLocation(x, y))
	}

	def randomGameLocation(x: Int, y: Int) = {
	    val c = Coordinates(x,y)
		if (Util.randomBoolean) GameLocation.corridor(c)
		else if (Util.randomBoolean) if (Util.randomBoolean) GameLocation.point(c) else GameLocation.corridor(c)
		else if (Util.randomBoolean) GameLocation.wall(c)
		else GameLocation.hole(c)
	}

	def createMap(mapString: String): (String,Option[GameMap]) = {

		val mapLines = mapString split " " map ((s:String) => (s filter (_ != '"'))) 
		val height = mapLines.size
		val width = mapLines(0).size
		val locs = mutable.Map[Coordinates, GameLocation]()
		var message = ""
		var valid = true

		try {
			for (i <- 0 until height; j <- 0 until width) {
				val newLoc = mapLines(i)(j) match {
				case '_' => GameLocation.corridor(Coordinates(i,j))
				case 'x' => GameLocation.wall(Coordinates(i,j))
				case 'u' => GameLocation.hole(Coordinates(i,j))
				case '.' => GameLocation.point(Coordinates(i,j))
				case other => {message = "Unknown character " + other; valid = false; GameLocation.corridor(Coordinates(i,j))}
				}
				locs.put(Coordinates(i,j), newLoc)   
			}
		} catch {
		case e: Exception => {valid = false; message = e.toString}
		}

		if (valid) {
			("SUCCESS",Some(GameMap(immutable.Map[Coordinates, GameLocation]() ++ locs)))
		} else {
			(message, None)
		}
	}

	def emptyMap() = {
		GameMap(new immutable.HashMap[Coordinates, GameLocation]{(Coordinates(0,0), 
				GameLocation.corridor(Coordinates(0,0)))})      
	}

	def printMap(map: GameMap) {
		for (i <- -1 until map.height + 1) {
			val line = for (j <- -1 until map.width + 1) 
				yield map.get(Coordinates(i,j)) match {
				case Some(gl) => consoleMarker(gl)
				case None => 'X'
			}
			println(line.mkString)
		}
	}

	private def consoleMarker(loc: GameLocation): Char = {
			if (loc.passable) {
				if (loc.hole) 'u' else if (loc.point) '.' else '_'
			} else 'x'
	}
}
